package myzd.config;

import libedge.annotations.Authentication;
import libedge.domain.exceptions.GenericException;
import lombok.extern.slf4j.Slf4j;
import myzd.api.code.CodeUtils;
import myzd.api.controllers.Access;
import myzd.api.domain.UserIdentity;
import myzd.services.StateCacheService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.Map;

@Slf4j
@ControllerAdvice
public class OrderUserIdentityAdapter extends WebMvcConfigurerAdapter {
  @Autowired
  private UserIdentity userIdentity;
  @Value("${source.intranet.secret}")
  private String secret;
  @Autowired
  private StateCacheService stateCacheService;

  //添加拦截器方法
  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    // authentication
    registry.addInterceptor(new HandlerInterceptor() {
      @Override
      public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("Authorization");
        if ("OPTIONS".equals(request.getMethod()) || StringUtils.isEmpty(token)) {
          return true;
        }
        if (StringUtils.isBlank(token)) {
          log.error("user token: {}", userIdentity);
          throw new GenericException(CodeUtils.ERROR_HEADER_CODE, CodeUtils.getErrText(CodeUtils.ERROR_HEADER_CODE));
        }
        Map<String, String> stateMap = stateCacheService.getState(token);
        HttpSession httpSession = request.getSession();
        userIdentity.setMobile(httpSession.getAttribute("mobile") == null ? "" : httpSession.getAttribute("mobile").toString());
        userIdentity.setId(httpSession.getAttribute("uid") == null ? "" : httpSession.getAttribute("uid").toString());
        userIdentity.setName(httpSession.getAttribute("name") == null ? "" : httpSession.getAttribute("name").toString());
        userIdentity.setRole(httpSession.getAttribute("role") == null ? "" : httpSession.getAttribute("role").toString());
        if (httpSession.getAttribute("uid") != null) {
          userIdentity.setUserId(new Long(httpSession.getAttribute("uid").toString()));
        }
        if (httpSession.getAttribute("sub") != null) {
          userIdentity.setUserId(new Long(httpSession.getAttribute("sub").toString()));
        }
        HandlerMethod handlerMethod = HandlerMethod.class.cast(handler);
        if (handlerMethod.hasMethodAnnotation(Authentication.class)) {
          authorize();
        }
        Authentication authentication = handlerMethod.getBeanType().getAnnotation(Authentication.class);
        if (authentication != null) {
          authorize();
        }
        return true;
      }

      @Override
      public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
      }

      @Override
      public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
      }
    });


    // authorize
    registry.addInterceptor(new HandlerInterceptor() {
      @Override
      public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if ("OPTIONS".equals(request.getMethod())) {
          return true;
        }
        //加入权限拦截
        // 获取出方法上的Access注解
        // 将handler强转为HandlerMethod, 前面已经证实这个handler就是HandlerMethod
        HandlerMethod handlerMethod = HandlerMethod.class.cast(handler);
        if (handlerMethod.hasMethodAnnotation(Authentication.class)) {
          authorizeAuthentication(handlerMethod.getMethodAnnotation(Authentication.class));
        }
        Authentication authentication = handlerMethod.getBeanType().getAnnotation(Authentication.class);
        if (authentication != null) {
          authorizeAuthentication(authentication);
          // 从方法处理器中获取出要调用的方法
          Method method = handlerMethod.getMethod();
          Access access = method.getAnnotation(Access.class);
          if (access == null) {
            // 如果注解为null, 说明不需要拦截, 直接放过
            return true;
          }
          if (access.authorities().length > 0) {
            // 如果权限配置不为空, 则取出配置值
            String[] authorities = access.authorities();

          }
        }
        return true;
      }

      @Override
      public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
      }

      @Override
      public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
      }
    });
  }

  private void authorizeAuthentication(Authentication authentication) throws GenericException {
    if (StringUtils.isEmpty(userIdentity.getId())) {
      log.error("user unauthenticated. userIdentity: {}", userIdentity);
      throw new GenericException("2411006", "unauthenticated");
    }
  }

  private void authorize() throws GenericException {
    if (StringUtils.isEmpty(userIdentity.getId())) {
      log.error("user unauthenticated. userIdentity: {}", userIdentity);
      throw new GenericException("2411006", "unauthenticated");
    }
  }

  /**
   * 查看controller权限是否满足
   *
   * @param annotation
   * @param authorities
   */
/*  private void hasPermission(JwtAuthorization annotation, String[] authorities) {

  }*/
}

